<template>
	<!-- v-if="progressName" -->
	<div class="per-list" v-if="uploadList.length > 0">
		<div class="header-list">
			<div @click="isShow = true" class="left-span">
				<img src="./上传.png" alt="" />上传进度
				<!-- <span class="num">{{ countInProgress }}/{{ uploadList.length }}</span> -->
			</div>
			<div @click="isShow = false"><img v-if="isShow" src="./关闭.png" alt="" style="width: 16px; height: 16px" /></div>
		</div>
		<div class="zip-list" v-if="isShow && uploadList.length > 0" v-for="(item, index) in uploadList" :key="index">
			<span
				>{{ index + 1 }}.{{ item.fileName }}
				<text :style="getTextStyle(item.type)" class="ml10">{{ item.type }}</text>
			</span>
			<el-progress :percentage="Number(item.percentage)"></el-progress>
		</div>
	</div>
	<el-dialog
		:title="form.fileDataSourceId && isRelease ? '发布图层' : form.fileDataSourceId ? '编辑资源' : '创建资源'"
		:width="600"
		v-model="visible"
		:close-on-click-modal="false"
		:destroy-on-close="true"
		draggable
		id="limit_dialog"
		@close="closeDialog"
		append-to-body
		:modal="progressName ? false : true"
	>
		<el-form ref="menuDialogFormRef" :model="form" :rules="rules" label-width="100px">
			<el-form-item label="数据源分类" prop="dataSourceType">
				<div class="flex w-full">
					<p
						class="flex justify-center items-center tabList cursor-pointer gap-2"
						v-for="(item, index) in tabList"
						:key="item.text"
						:disabled="disabled"
						@click="tabHandle(item, index)"
						:class="[disabled ? 'disabled-style' : '', active == index ? 'actived' : '']"
					>
						<i class="iconfont" :class="item.icon"></i>
						<span>{{ item.text }}</span>
					</p>
				</div>
			</el-form-item>

			<el-row :gutter="20">
				<el-col :span="12">
					<el-form-item label="数据类型" prop="dataType">
						<el-select v-model="form.dataType" placeholder="请选择类型" :suffix-icon="IconDropDown" :disabled="disabled">
							<el-option v-for="item in optionsType" :key="item.value" :label="item.label" :value="formattedValue(item.value)" />
						</el-select>
					</el-form-item>
				</el-col>
			</el-row>
			<el-form-item />
			<div v-if="form.dataType || form.fileDataSourceId">
				<el-form-item label="资源名称" prop="fileNameCh">
					<el-input v-model.trim="form.fileNameCh" clearable placeholder="请输入资源名称" :disabled="isRelease"></el-input>
				</el-form-item>
				<el-form-item label="资源描述" prop="fileRemarks">
					<el-input v-model.trim="form.fileRemarks" type="textarea" clearable placeholder="请输入资源描述" :disabled="isRelease"></el-input>
				</el-form-item>
				<!-- <el-form-item v-if="form.dataType != 4" label="文件类型" prop="serviceType">
					<el-radio-group v-model="form.serviceType" :disabled="disabled">
						<el-radio-button :class="form.serviceType == 1 && !disabled ? 'actived' : ''" :label="1">文件上传</el-radio-button>
						<el-radio-button :class="form.serviceType == 2 && !disabled ? 'actived' : ''" :label="2">{{
							active == 0 ? '服务路径' : '本地路径'
						}}</el-radio-button>
					</el-radio-group>
				</el-form-item> -->
				<el-form-item v-if="active === 0 && form.serviceType == 1" label="文件路径" prop="sourceServiceUrl">
					<el-input
						v-model.trim="form.sourceServiceUrl"
						clearable
						:placeholder="uploadTip"
						disabled
						style="width: 84%; margin-right: 10px"
					></el-input>
					<el-form-item prop="fileList" v-if="form.serviceType == 1">
						<div class="flex">
							<el-upload
								v-if="!singleFilePart.fileList.length > 0"
								v-model:file-list="singleFilePart.fileList"
								class="upload-demo"
								:limit="1"
								:headers="headers"
								accept=".zip"
								:show-file-list="false"
								:on-change="selectSinglePartFile"
								:before-upload="beforeUpload"
								:auto-upload="false"
							>
								<el-button type="primary" :disabled="disabled">浏览</el-button>
							</el-upload>
						</div>
					</el-form-item>
				</el-form-item>
				<el-form-item v-if="active !== 0 && form.dataType != 4 && form.serviceType == 1" label="文件路径" prop="sourceServiceUrl">
					<el-input
						v-model.trim="form.sourceServiceUrl"
						clearable
						:placeholder="uploadTip"
						disabled
						style="width: 84%; margin-right: 10px"
					></el-input>
					<el-form-item prop="fileList" v-if="form.serviceType == 1">
						<div class="flex">
							<el-upload
								v-if="!singleFilePart.fileList.length > 0"
								v-model:file-list="singleFilePart.fileList"
								class="upload-demo"
								:limit="1"
								:headers="headers"
								accept=".zip"
								:show-file-list="false"
								:on-change="selectSinglePartFile"
								:before-upload="beforeUpload"
								:auto-upload="false"
							>
								<el-button type="primary" :disabled="disabled">浏览</el-button>
							</el-upload>
						</div>
					</el-form-item>
				</el-form-item>
				<!-- <el-form-item v-if="active === 0 && form.serviceType == 2" label="服务路径" prop="sourceServiceUrl">
					<el-input v-model.trim="form.sourceServiceUrl" clearable placeholder="请输入服务路径" :disabled="disabled"></el-input>
				</el-form-item>
				<el-form-item v-if="active !== 0 && form.dataType != 4 && form.serviceType == 2" label="本地路径" prop="sourceServiceUrl">
					<el-input v-model.trim="form.sourceServiceUrl" clearable placeholder="请输入本地路径" :disabled="disabled"></el-input>
				</el-form-item> -->
				<el-col :span="24" class="mb20">
					<el-row :gutter="20">
						<el-form-item v-if="active == 1 && form.dataType == 4" label="连接参数" prop="host">
							<el-col :span="12">
								<el-input v-model.trim="form.host" style="width: 240px" clearable placeholder="请输入地址" :disabled="disabled"></el-input>
							</el-col>
							<el-form-item prop="port">
								<el-col :span="12">
									<el-input
										v-model.trim="form.port"
										style="width: 190px; margin-left: 30px"
										clearable
										placeholder="请输入端口"
										:disabled="disabled"
									></el-input>
								</el-col>
							</el-form-item>
						</el-form-item>
					</el-row>
				</el-col>

				<el-form-item v-if="active == 1 && form.dataType == 4" label="数据库" prop="databaseName">
					<el-input v-model.trim="form.databaseName" clearable placeholder="请输入" :disabled="disabled"></el-input>
				</el-form-item>

				<el-form-item v-if="active == 1 && form.dataType == 4" label="用户名" prop="username">
					<el-input v-model.trim="form.username" clearable placeholder="请输入" :disabled="disabled"></el-input>
				</el-form-item>

				<el-form-item v-if="active == 1 && form.dataType == 4" label="密码" prop="password">
					<el-input v-model.trim="form.password" type="password" clearable placeholder="请输入" :disabled="disabled"></el-input>
				</el-form-item>
			</div>
			<div class="text-center">
				<el-button v-if="active == 1 && form.dataType == 4" type="primary" class="test-btn" @click="testGis(menuDialogFormRef)">测试连接</el-button>
				<el-button @click="closeDialog">取消</el-button>
				<el-button type="primary" @click="saveFileUpload(menuDialogFormRef)">{{ isRelease ? '发布' : '保存' }}</el-button>
			</div>
		</el-form>
	</el-dialog>
</template>
<script setup lang="ts">
import { useMessage } from '/@/hooks/message';
import { ref } from 'vue';
import DropDown from '/@/assets/icons/drop-down.svg';
import { getIdProject } from '/@/api/admin/role';
import { useUserInfo } from '/@/stores/userInfo';
import { Session } from '/@/utils/storage';
import axios from 'axios';
import { useDict } from '/@/hooks/dict';
import { version } from 'nprogress';
import { addFileData, editFileData, updateDataSourceStatus, testPostGIS } from '/@/api/project/index';
import { Delete } from '@element-plus/icons-vue/dist/types';
const visible = ref(false);
const form = ref({
	serviceType: 1,
});
const disabled = ref(false);
const isRelease = ref(false); //是否发布基础底图
const percentage = ref(0);
const progressName = ref(false);
const rules = ref({
	fileNameCh: [{ required: true, message: '不能为空', trigger: 'blur' }],
	fileRemarks: [{ required: true, message: '不能为空', trigger: 'blur' }],
	dataType: [{ required: true, message: '请选择', trigger: 'blur' }],
	sourceServiceUrl: [{ required: true, message: '不能为空', trigger: 'blur' }],
	serviceType: [{ required: true, message: '服务类型不能为空', trigger: 'blur' }],
	databaseName: [{ required: true, message: '数据库不能为空', trigger: 'blur' }],
	username: [{ required: true, message: '用户名不能为空', trigger: 'blur' }],
	password: [{ required: true, message: '密码不能为空', trigger: 'blur' }],
	host: [{ required: true, message: '地址不能为空', trigger: 'blur' }],
	port: [{ required: true, message: '端口不能为空', trigger: 'blur' }],
});
const active = ref('0');
const menuDialogFormRef = ref('');
const accept = ref(['zip', 'rar']);
const emit = defineEmits(['refresh']);
const { proxy } = getCurrentInstance();
const isShow = ref(false);
const uploadList = ref([]); //文件上传列表
const baseMap = ref([
	{
		label: '瓦片地图',
		value: '6',
		tip: '选择本地zip格式文件路径上传',
		accept: ['zip'],
	},
	{
		label: '地形',
		value: '7',
		tip: '选择本地zip格式文件路径上传',
		accept: ['zip'],
	},
	{
		label: 'WMS服务',
		value: '8',
		tip: '选择本地zip格式文件路径上传',
		accept: ['zip'],
	},
]);

const vectorList = ref([
	{
		label: 'Shapefile',
		value: '1',
		tip: '选择本地zip格式文件路径上传',
		accept: ['zip'],
	},
	{
		label: 'Tif',
		value: '2',
		tip: '选择本地fbx、glb格式文件路径上传',
		accept: ['tif', 'tiff'],
	},
	{
		label: 'PostGIS',
		value: '4',
		tip: '选择本地zip格式文件路径上传',
		accept: ['zip'],
	},
]);

const modelList = ref([
	{
		label: '3Dtiles',
		value: '3',
		tip: '选择本地zip格式文件路径上传',
		accept: ['zip'],
	},
	{
		label: 'FBX/GLB',
		value: '5',
		tip: '选择本地fbx、glb格式文件路径上传',
		accept: ['zip'],
	},
]);
const singleFilePart = ref({
	file: '',
	fileList: [],
	fileData: [],
	partNum: 0, // 总分片数
	fileName: '', // 文件名
	fileUid: '', // 文件uuid
	fileMd5: '', // 文件Md5
	isStop: false,
	randomCount: 0,
});
const fileType = ref('');
// 方法返回对应的样式对象
const getTextStyle = (type) => {
	switch (type) {
		case '上传中':
			return { color: '#557AD7' };
		case '上传失败':
			return { color: 'red' };
		default:
			return { color: '#4dc029' };
	}
};
const tabList = ref([
	{
		text: '基础底图',
		tip: '支持上传shp的zip文件',
		accept: ['zip', 'rar', 'dem', 'dom'],
	},
	{
		text: '二维矢量',
		tip: '支持上传shp的zip文件',
		accept: ['tif', 'tiff', 'zip', 'rar'],
	},
	{
		text: '三维模型',
		tip: '支持上传shp的zip文件',
		accept: ['3dtiles', 'tiles', 'glb', 'fbx', 'zip', 'rar'],
	},
]);
const IconDropDown = {
	render: () => {
		return h('img', { src: DropDown });
	},
};
const uploadFlag = ref(true);
const headers = computed(() => {
	return {
		Accept: 'application/octet-stream',
	};
});
const uploadTip = ref('请上传文件');

// 选择格式
const optionsType = computed(() => {
	switch (active.value) {
		case 0:
			return baseMap.value;
		case 1:
			return vectorList.value;
		case 2:
			return modelList.value;
		default:
			return baseMap.value;
	}
});

watch(
	() => form.value.sourceServiceUrl,
	(newVal, oldVal) => {
		if (!form.value.sourceServiceUrl) {
			singleFilePart.value.file = '';
			singleFilePart.value.fileList = [];
			singleFilePart.value.fileData = [];
			singleFilePart.value.percentage = 0; // 总分片数
			singleFilePart.value.fileName = ''; // 文件名
			singleFilePart.value.fileUid = ''; // 文件uuid
			singleFilePart.value.fileMd5 = ''; // 文件Md5
			singleFilePart.value.isStop = false;
			singleFilePart.value.randomCount = 0;
		}
	}
);

const formattedValue = (value) => {
	form.value.serviceType = 1;
	return form.value.fileDataSourceId ? Number(value) : value;
};
//数据源类型切换
const tabHandle = (item, index) => {
	if (disabled.value) return;
	form.value.dataType = '';
	form.value = {};
	active.value = index;
	accept.value = item.accept;
};

//上传成功
const beforeUpload = (file: any) => {
	if (accept.value.length) {
		const fileName = file.name.split('.');
		const fileExt = fileName[fileName.length - 1];
		// fileType.value = fileExt;
		const isTypeOk = accept.value.indexOf(fileExt) >= 0;
		const adminId = useUserInfo().userInfos.user.userId;
		if (!isTypeOk && adminId !== '1') {
			useMessage().error(`文件格式不正确, 请上传${accept.value.join('/')}格式文件!`);
			singleFilePart.value.fileList = [];
		}
	}
};

// 下面是单文件分片上传的一些方法
function selectSinglePartFile(file, fileList) {
	singleFilePart.value.file = file;
	singleFilePart.value.fileList = [];
	singleFilePart.value.fileList.push(file);
	singleFilePart.value.fileName = file.name;
	form.value.sourceServiceUrl = file.name;
}
// 测试PostGIS
const testGis = async (forms: any) => {
	try {
		const valid = await forms.validate();
		if (valid) {
			form.value.id = form.value.fileDataSourceId;
			form.value.dbType = 'postgresql';
			delete form.value.fileDataSourceId;

			let newTestForm = {
				databaseName: form.value.databaseName,
				dbType: form.value.dbType,
				host: form.value.host,
				password: form.value.password,
				port: form.value.port,
				username: form.value.username,
			};
			const res = await testPostGIS(newTestForm);
			if (res.code == 0) {
				useMessage().success('连接成功');
			}
		}
	} catch (err) {
		if (err && err.msg) {
			useMessage().error(err.msg);
		} else {
			useMessage().error('发生错误，请稍后再试');
		}
	}
};

// 保存 基本底图  新增、编辑
const saveFileUpload = async (forms: any) => {
	form.value.dataSourceType = active.value + 1;
	delete form.value.serviceType;
	// 发布、文件类型1 并且有上传文件
	if (singleFilePart.value.fileList.length > 0) {
		uploadFlag.value = true;
		// 基础底图文件类型是 文件上传
		singleFilePartUpload(forms);
	} else {
		// 基础底图文件类型是 服务路径
		await forms.validate((valid) => {
			if (valid) {
				if (!form.value.fileDataSourceId) {
					if (form.value.dataType == 4) {
						delete form.value.dbType;
					}
					addFileData(form.value)
						.then((res) => {
							if (res.data) {
								useMessage().success('新增成功！');
								visible.value = false;
								reset();
								emit('refresh');
							}
						})
						.catch((err) => {
							useMessage().error(err.msg);
						});
				} else {
					form.value.id = form.value.fileDataSourceId;
					if (isRelease.value) {
						form.value.publishStatus = 1;
						updateDataSourceStatus(form.value)
							.then((res) => {
								if (res) {
									useMessage().success('发布成功！');
									visible.value = false;
									reset();
									emit('refresh');
								}
							})
							.catch((err) => {
								useMessage().error(err.msg);
							});
					} else {
						let newForm = {
							fileNameCh: form.value.fileNameCh,
							fileRemarks: form.value.fileRemarks,
							id: form.value.id,
						};

						editFileData(newForm)
							.then((res) => {
								if (res.data) {
									useMessage().success('编辑成功！');
									visible.value = false;
									reset();
									emit('refresh');
								}
							})
							.catch((err) => {
								useMessage().error(err.msg);
							});
					}
				}
			}
		});
	}
};

// 二三维分片上传
async function singleFilePartUpload(forms: any) {
	switch (form.value.dataType) {
		case '1':
			fileType.value = 'shp';
			break;
		case '2':
			fileType.value = 'tif';
			break;
		case '3':
			fileType.value = 'tiles';
			break;
		case '4':
			fileType.value = '';
			break;
		case '5':
			fileType.value = 'fbx';
			break;
		case '6':
			fileType.value = 'dom';
			break;
		case '7':
			fileType.value = 'dem';
			break;
		case '8':
			fileType.value = '';
			break;
		default:
		// 代码块
	}
	const chinesePattern = /[\u4e00-\u9fa5]/;
	if (chinesePattern.test(singleFilePart.value.fileName)) {
		return useMessage().error('文件名不能包含中文');
	}
	await forms.validate(async (valid) => {
		if (!valid) {
			return;
		}
		// 初始化文件上传信息
		let fileUploadInfo = {
			fileUid: singleFilePart.value.file.uid,
			uploadFlag: true,
			fileName: singleFilePart.value.file.name,
			totalSize: singleFilePart.value.file.size,
			partNum: 0,
			percentage: 0,
			progressName: true,
			file: singleFilePart.value.file,
			type: '上传中',
			parts: [], // 存储每个分片的信息
		};
		let newForm = {};
		Object.assign(newForm, form.value);
		fileUploadInfo.fileList = [];
		fileUploadInfo.fileList.push(singleFilePart.value.file);
		uploadList.value.push(fileUploadInfo);
		isShow.value = true; //打开上传列表
		let url = proxy.baseURL + '/geoserver/file/singleFilePartUpload';
		let partSize = 5 * 1024 * 1024; // 5MB
		let totalSize = fileUploadInfo.totalSize;
		fileUploadInfo.fileUid = fileUploadInfo.fileUid;
		fileUploadInfo.partNum = Math.ceil(totalSize / partSize); // 5MB一片
		// progressName.value = true;
		// console.log(fileUploadInfo.partNum, '分成多少片');
		let num = 0;
		for (let i = 0; i < fileUploadInfo.partNum; i++) {
			if (!uploadFlag.value) {
				break; // 如果 uploadFlag 为 false，跳出循环
			}

			const fileParam = new FormData();
			fileParam.append('filePart', fileUploadInfo.file.raw.slice(i * partSize, (i + 1) * partSize));
			fileParam.append('partIndex', i);
			fileParam.append('partNum', fileUploadInfo.partNum);
			fileParam.append('fileUid', fileUploadInfo.fileUid);
			fileParam.append('totalSize', totalSize);
			fileParam.append('fileService', 'minIOService');
			fileParam.append('fileType', fileType.value);
			fileParam.append('dbType', 'postgres');
			fileParam.append('fileName', fileUploadInfo.fileName);
			fileParam.append('projectName', ''); //form.value.projectName
			fileParam.append('fileRemarks', newForm.fileRemarks);
			fileParam.append('fileNameCh', newForm.fileNameCh);
			fileParam.append('dataSourceType', newForm.dataSourceType);
			const headers = { Authorization: 'Bearer ' + Session.get('token') };
			try {
				const response = await axios({
					url: url,
					method: 'post',
					data: fileParam, //data表示参数在请求（body）中，后端可以通过流直接读取，SpringMvc可以使用RequestBody注解获取
					headers: headers,
					dataType: 'json',
				});

				// 检查响应对象是否为 undefined 或 null
				// console.log('看res', response.data);
				if (!response || !response.data) {
					throw new Error('服务器未返回有效响应');
				}
				const resp = response.data;

				if (resp.code !== 0) {
					throw new Error(resp.msg || '未知错误');
				}

				fileUploadInfo.percentage = Number((((i + 1) / fileUploadInfo.partNum) * 100).toFixed(0));

				// console.log('进度------',fileUploadInfo.partNum,i, fileUploadInfo.percentage);
				let index = uploadList.value.findIndex((item) => item.fileUid === fileUploadInfo.fileUid);

				if (index != -1) {
					uploadList.value[index].percentage = (((i + 1) / fileUploadInfo.partNum) * 100).toFixed(0);
				}

				uploadFlag.value = true;
				emit('refresh');

				// 判断最后一个分片文件传完之后，后台检验文件上传情况
				if (i === fileUploadInfo.partNum - 1) {
					fileUploadInfo.percentage = 100;
					fileUploadInfo.progressName = false;
					useMessage().success('保存完成');
					visible.value = false;
					for (let i = 0; i < uploadList.value.length; i++) {
						if (uploadList.value[i].fileUid == fileUploadInfo.fileUid) {
							uploadList.value[i].type = '上传成功';
						}
					}
					setTimeout(() => {
						emit('refresh');
						reset();
					}, 500);
				} else {
					// 如果不是最后一个部分，确保进度不会超过99%
					uploadList.value[index].percentage = Math.min(99, (((i + 1) / fileUploadInfo.partNum) * 100).toFixed(0));
				}
			} catch (error) {
				for (let i = 0; i < uploadList.value.length; i++) {
					if (uploadList.value[i].fileUid == fileUploadInfo.fileUid) {
						uploadList.value[i].type = '上传失败';
					}
				}
				fileUploadInfo.progressName = false;
				// visible.value = false;
				useMessage().error(error.message);
				emit('refresh');
				fileUploadInfo.uploadFlag = false;
				break;
			}
		}
	});

	visible.value = false;
	emit('refresh');
}
function openDialog(type: any, row: any) {
	disabled.value = false;
	isRelease.value = false;
	visible.value = true;
	active.value = 0;
	if (type !== 'add') {
		disabled.value = true;
		nextTick(() => {
			active.value = Number(row.dataSourceType) - 1;
			Object.assign(form.value, row);
			if (form.value.dataSourceType == 2) {
				form.value.serviceType = 1;
			} else {
				form.value.serviceType = 2;
			}

			nextTick(() => {
				if (!form.value.fileId) {
					form.value.serviceType = 2;
				}
			});
		});
		// 发布基础底图
		if (type == 'release') {
			isRelease.value = true;
		}
	}
}

//重置表单
const reset = () => {
	form.value = {};
	singleFilePart.value.fileList = [];
};
function closeDialog() {
	visible.value = false;
	uploadFlag.value = false;
	progressName.value = false;
	reset();
}
defineExpose({
	openDialog,
	reset,
	uploadList,
});
</script>
<style scoped lang="scss">
.tabList {
	background: #eaf1ff;
	border-radius: 2px;
	color: #3156a5;
	width: 33%;
	padding: 0px 6px;
}
.actived {
	background: #3156a5;
	color: #fff;
}
.text-center {
	text-align: right;
	margin-top: 18px;
}
.test-btn {
	position: absolute;
	left: 120px;
}
.disabled-style {
	cursor: not-allowed !important; /* 鼠标样式表示不可点击 */
	/* 其他禁用样式 */
}
::v-deep .el-progress {
	width: 200px;
	position: relative;
	bottom: 2%;
	left: 2%;
}
.per-list {
	background-color: rgb(242, 242, 242);
	// height: 200px;
	width: 280px;
	position: absolute;
	z-index: 99;
	left: 2%;
	bottom: 2%;
	padding: 12px;
	.header-list {
		display: flex;
		justify-content: space-between;
		.left-span {
			display: flex;
			line-height: 34px;
			color: #7e7777;
			img {
				width: 30px;
				height: 30px;
				margin-right: 8px;
			}
			.num {
				color: #3156a5;
				text-decoration: underline;
				margin: 0 8px;
			}
		}
	}
	.zip-list {
		background: #fff;
		padding: 0 10px;
	}
}
</style>
